Locating, analyzing and correcting suspected faults or bugs in a computer program is a process known as “debugging.” Typically, a programmer uses another computer program commonly known as a “debugger” to debug a program under development.
Conventional debuggers typically support two primary operations to assist a computer programmer. A first operation supported by conventional debuggers is a “step” function, which permits a computer programmer to process instructions (also known as “statements”) in a computer program one-by-one, and see the results upon completion of each instruction. While the step operation provides a programmer with a large amount of information about a program during its execution, stepping through hundreds or thousands of program instructions can be extremely tedious and time consuming, and may require a programmer to step through many program instructions that are known to be error-free before a set of instructions to be analyzed are executed.
To address this difficulty, a second operation supported by conventional debuggers is a breakpoint operation, which permits a computer programmer to identify with a “breakpoint” a precise instruction for which it is desired to halt execution of a computer program during execution. As a result, when a computer program is executed by a debugger, the program executes in a normal fashion until a breakpoint is reached, and then stops execution and displays the results of the computer program to the programmer for analysis. Most breakpoints supported by conventional debuggers are unconditional, meaning that once such a breakpoint is reached, execution of the program is always halted.
Typically, step operations and breakpoints are used together to simplify the debugging process. Specifically, a common debugging operation is to set a breakpoint at the beginning of a desired set of instructions to be analyzed, and then begin executing the program. Once the breakpoint is reached, the program is halted, and the programmer then steps through the desired set of instructions line by line using the step operation. Consequently, a programmer is able to quickly isolate and analyze a particular set of instructions without having to step through irrelevant portions of a computer program.
However, one significant drawback of utilizing breakpoints is the identification of locations to set the breakpoints. A “good” breakpoint location may be a location in the code just before the bug is encountered. Although a programmer can sometimes identify a “good” breakpoint location based upon his or her familiarity with the computer program's code and/or error conditions, oftentimes a programmer is not familiar with the computer program that he or she is trying to debug. For instance, the code of the program may have been written by a colleague, and as such, it may be difficult to identify a good location for a breakpoint other than by chance.
This is problematic because some instructions in a computer program are executed fairly often for different purposes, and incorrect placement of breakpoints may result in many needless stoppages before a desired stoppage is encountered. This problem is especially pronounced in object-oriented programming (OOP) and other highly modular languages, where a single general purpose portion of a computer program may be executed in a number of different situations for different purposes.
With an object-oriented programming language, for example, a program is constructed from a number of “objects”, each of which including data and/or one or more sets of instructions (often referred to as “routines” or “methods”) that define specific operations that can be performed on the data. A large number of objects may be used to build a computer program, with each object interacting with other objects in the computer program to perform desired operations. Some general purpose objects in a computer program, in particular, may have routines that are called by many different objects, and thus placing a breakpoint in a routine of such an object may result in hundreds of unwanted stoppages prior to occurrence of a desired stoppage. A computer programmer may be able to alleviate this problem to some extent by relocating the breakpoints but this is also typically a tedious and time-consuming process.
In addition to the delay and waste in time and/or resources that may be caused by these unwanted stoppages, a large number of unwanted stoppages are also problematic because it may indicate that this code path (i.e., series of instruction in order of execution) is a frequently executed code path in the computer program, also known as a “hot path”. However, the bugs in a computer program are oftentimes associated with a code path that is infrequently executed, also known as a cold path; otherwise, the bug would have already been encountered and resolved much earlier in the development process.
Even the identification of good locations to set conditional breakpoints, as opposed to unconditional breakpoints, is problematic. In particular, some debuggers support the use of conditional breakpoints, which only halt execution of a program when a variable used by the program is set to a predetermined value at the time such a breakpoint is reached. However, once again, unless the programmer knows of a specific condition to utilize, for example, based upon his or her familiarity with the computer program, and the condition is sufficiently unique, the programmer may also be faced with hundreds of unwanted stoppages.
Therefore, a significant need continues to exist for an improved manner of debugging computer programs, specifically in the area of identifying breakpoint locations, that is not primarily dependent on a programmer's familiarity with the program.